/* Utility scripts for Pardus Sector Tool
* (C) Yassen 2010
*
* Functions:
*
* Send(options)
* Check()
* Login(username, password)
* Register(username, password)
* AddSector(name, data)
* AddPricelist(name, data)
* UpdateSector(name, data)
* UpdatePricelist(name, data)
* DeleteSector(name)
* DeletePricelist(name)
* GetSectors()
* GetPricelists()
* GetSector(name)
* GetPricelist(name)
* RenameSector(oldName, newName)
* RenamePricelist(oldName, newName)
* GetSectorCode(name)
* 
*/

// Messages
var MsgRegister = "register";
var MsgLogin = "login";
var MsgGetSettings = "getsettings";
var MsgDeleteUser = "deleteuser";
var MsgAddSector = "addsector";
var MsgAddPricelist = "addpricelist";
var MsgUpdateSector = "updatesector";
var MsgUpdatePricelist = "updatepricelist";
var MsgRenameSector = "renamesector";
var MsgRenamePricelist = "renamepricelist";
var MsgDeleteSector = "deletesector";
var MsgDeletePricelist = "deletepricelist";
var MsgGetSectors = "getsectors";
var MsgGetPricelists = "getpricelists";
var MsgGetSector = "getsector";
var MsgGetPricelist = "getpricelist";
var MsgGetSectorCode = "getsectorcode";

// Statuses
var STATUS_LOGIN_FAILED = "Login Failed";
var STATUS_CORRUPT = "Corrupt";
var STATUS_ERROR = "Error";
var STATUS_OK = "Okay";


Utility.Server.Cache = {
  Sectors: $H(),
  Pricelists: $H()
};

Utility.Server.Send = function(options)
{
  // Options:
  //   action
  //   data
  //   username
  //   password
  //   callback
  //   cache

  var defaultOptions = { action: "", data: {}, cache: false, username: User.Username, password: User.Password, callback: $empty };

  options = $H(options).combine(defaultOptions);

  this.action = options.action;
  this.username = options.username;
  this.password = options.password;
  this.data = $H(options.data);
  this.cache = options.cache;

  var url = new URI("./server/index.php");
  url.setData({ action: this.action,
    protocol: ProtocolVersion,
    username: this.username,
    password: this.password
  });

  LoadingWindow.Show();
  var request = new Request({ url: url.toString(),
    method: "POST",
    noCache: (!this.cache),
    onSuccess: (function(responseText, responseXML)
    {
      LoadingWindow.Hide();
      var result = JSON.decode(responseText);
      var error = true;

      switch (result["Status"])
      {
        case STATUS_CORRUPT:
          alert("Server <-> Client API Error!");
          break;

        case STATUS_ERROR:
          break;

        case STATUS_LOGIN_FAILED:
          User.Username = "";
          User.Password = "";
          User.Verified = false;
          LoginWindow.Show();
          break;

        case STATUS_OK:
          error = false;
          break;
      }

      this.callback(result, error);

    }).bind({ callback: options.callback })
  });

  request.send(this.data.toQueryString());
}

Utility.Server.Check = function()
{
  if (!User.Verified)
  {
    LoginWindow.Show();
    return false;
  }
  else
    return true;
}

Utility.Server.Login = function(username, password, callback)
{
  password = b64_md5(password); // md5 hash

  Utility.Server.Send({ action: MsgLogin,
    username: username,
    password: password,
    callback: (function(result, error)
    {
      if (!error)
      {
        User.Username = this.username;
        User.Password = this.password;
        User.Verified = true;
        EventSink.fireEvent(MsgLogin, [result, this.username, this.password]);
      }
      
      this.callback(result, error);
    }).bind({ callback: callback, username: username, password: password })
  });

  return true;
}

Utility.Server.Register = function(username, password, callback)
{
  password = b64_md5(password); // md5 hash

  Utility.Server.Send({ action: MsgRegister,
    username: username,
    password: password,
    callback: (function(result, error)
    {
      if (!error)
      {
        User.Username = this.username;
        User.Password = this.password;
        User.Verified = true;
        EventSink.fireEvent(MsgRegister, [this.username, this.password]);
      }

      this.callback(result, error);
    }).bind({ callback: callback, username: username, password: password })
  });

  return true;
}

Utility.Server.AddSector = function(name, data, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgAddSector,
    data: { name: name, data: data },
    callback: (function(result, error)
    {
      if (!error)
        EventSink.fireEvent(MsgAddSector, [this.name, this.data]);

      this.callback(result, error);
    }).bind({ callback: callback, name: name, data: data })
  });

  return true;
}

Utility.Server.AddPricelist = function(name, data, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgAddPricelist,
    data: { name: name, data: data },
    callback: (function(result, error)
    {
      if (!error)
        EventSink.fireEvent(MsgAddPricelist, [this.name, this.data]);

      this.callback(result, error);
    }).bind({ callback: callback, name: name, data: data })
  });

  return true;
}

Utility.Server.UpdateSector = function(name, data, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgUpdateSector,
    data: { name: name, data: data },
    callback: (function(result, error)
    {
      if (!error)
        EventSink.fireEvent(MsgUpdateSector, [this.name, this.data]);

      this.callback(result, error);
    }).bind({ callback: callback, name: name, data: data })
  });

  return true;
}

Utility.Server.UpdatePricelist = function(name, data, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgUpdatePricelist,
    data: { name: name, data: data },
    callback: (function(result, error)
    {
      if (!error)
        EventSink.fireEvent(MsgUpdatePricelist, [this.name, this.data]);

      this.callback(result, error);
    }).bind({ callback: callback, name: name, data: data })
  });

  return true;
}

Utility.Server.DeleteSector = function(name, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgDeleteSector,
    data: { name: name },
    callback: (function(result, error)
    {
      this.callback(result, error);
    }).bind({ callback: callback })
  });

  return true;
}

Utility.Server.DeletePricelist = function(name, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgDeletePricelist,
    data: { name: name },
    callback: (function(result, error)
    {
      this.callback(result, error);
    }).bind({ callback: callback })
  });

  return true;
}

Utility.Server.GetSectors = function(callback)
{
  if (!Utility.Server.Check())
    return false;

  if (Utility.Server.Cache.Sectors.getLength() > 0)
  {
    this.callback(Utility.Server.Cache.Sectors.getKeys());
  }
  else
  {
    Utility.Server.Send({ action: MsgGetSectors,
      callback: (function(result, error)
      {
        this.callback(result["Sectors"], error);
      }).bind({ callback: callback })
    });
  }

  return true;
}

Utility.Server.GetPricelists = function(callback)
{
  if (!Utility.Server.Check())
    return false;

  if (Utility.Server.Cache.Pricelists.getLength() > 0)
  {
    this.callback(Utility.Server.Cache.Pricelists.getKeys());
  }
  else
  {
    Utility.Server.Send({ action: MsgGetPricelists,
      callback: (function(result, error)
      {
        this.callback(result["Sectors"], error);
      }).bind({ callback: callback })
    });
  }

  return true;
}

Utility.Server.GetSector = function(name, callback)
{
  if (!Utility.Server.Check())
    return false;

  if ($defined(Utility.Server.Cache.Sectors[name]))
  {
    callback(Utility.Server.Cache.Sectors[name]);
    return Utility.Server.Cache.Sectors[name];
  }
  else
  {
    Utility.Server.Send({ action: MsgGetSector,
      data: { name: name },
      callback: (function(result, error)
      {
        if (!error)
        {
          Utility.Server.Cache.Sectors[this.name] = result["Code"];
          Global.CachedSectors[result["MapName"]] = Utility.Sector.MapToTiles(result["Map"]);
          this.callback(result);
        }
      }).bind({ callback: callback, name: name })
    });
  }

  return true;
}

Utility.Server.GetPricelist = function(name, callback)
{
  if (!Utility.Server.Check())
    return false;

  if ($defined(Utility.Server.Cache.Pricelists[name]))
  {
    callback(Utility.Server.Cache.Pricelists[name]);
    return Utility.Server.Cache.Pricelists[name];
  }
  else
  {
    Utility.Server.Send({ action: MsgGetPricelist,
      data: { name: name },
      callback: (function(result, error)
      {
        if (!error)
        {
          Utility.Server.Cache.Pricelists[this.name] = result["Code"];
          this.callback(result["Code"]);
        }
      }).bind({ callback: callback, name: name })
    });
  }

  return true;
}

Utility.Server.RenameSector = function(oldName, newName, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgRenameSector,
    data: { oldName: oldName, newName: newName },
    callback: (function(result, error)
    {
      if (!error)
      {
        Utility.Server.Cache.Sectors[this.newName] = Utility.Server.Cache.Sectors[this.oldName];
        delete Utility.Server.Cache.Sectors[this.oldName];
      }

      this.callback(result, error);
    }).bind({ callback: callback, oldName: oldName, newName: newName })
  });

  return true;
}

Utility.Server.RenamePricelist = function(oldName, newName, callback)
{
  if (!Utility.Server.Check())
    return false;

  Utility.Server.Send({ action: MsgRenamePricelist,
    data: { oldName: oldName, newName: newName },
    callback: (function(result, error)
    {
      if (!error)
      {
        Utility.Server.Cache.Pricelists[this.newName] = Utility.Server.Cache.Pricelists[this.oldName];
        delete Utility.Server.Cache.Pricelists[this.oldName];
      }

      this.callback(result, error);
    }).bind({ callback: callback, oldName: oldName, newName: newName })
  });

  return true;
}

Utility.Server.GetSectorCode = function(name, callback)
{
  if (!callback)
    callback = $empty;

  if ($chk(Global.CachedSectors[name]))
  {
    callback(Global.CachedSectors[name]);
    return Global.CachedSectors[name];
  }
  else
  {
    Utility.Server.Send({ action: MsgGetSectorCode,
      data: { name: name },
      callback: (function(result, error)
      {
        if (!error)
          Global.CachedSectors[name] = Utility.Sector.MapToTiles(result["Code"]);

        this.callback(result["Code"], error);
      }).bind({ callback: callback, name: name })
    });
  }
}